1 module about_delegates; 2 3 import dunit; 4 import helpers; 5 6 class AboutDelegates { 7 mixin UnitTest; 8 9 // Delegates are function pointers with context information attached. 10 int delegate(int) call_me_later; // a delegate which takes an int and returns an int 11 12 class Foo { 13 private int y; 14 15 //constructor 16 this(int value) { 17 y=value; 18 } 19 20 int mymethod(int x) { 21 return x+y; 22 } 23 } 24 25 @Test 26 public void explicit_delegate() { 27 Foo foo = new Foo(3); 28 call_me_later = &foo.mymethod; 29 auto result=call_me_later(5); // call mymethod(5) 30 assertEquals(result, FILL_IN_THIS_NUMBER); 31 } 32 33 // -------------------------------------------------------------------------------- 34 // delegates are useful as "event receivers". Let's define a simple GUI-like class 35 36 alias ClickHandler=void delegate(Button); 37 38 class Button { 39 40 private ClickHandler[] handlers; 41 42 private int click_counter; //some button properties 43 private string name="UNTITLED"; 44 private string color="DEFAULT"; 45 46 void click() { // executes user defined callbacks 47 // giving each callback full access to this "Button" context 48 foreach(h; handlers) { 49 h(this); 50 } 51 click_counter++; 52 } 53 void registerHandler(ClickHandler func) 54 { 55 handlers~=func; 56 } 57 58 @property string state() { 59 import std.format : format; 60 return format("you clicked %d times the button %s with color %s",click_counter,name,color); 61 } 62 63 } 64 65 // now the class user can "attach" event handlers to instances of the class 66 // in order to change class default behavior 67 68 @Test 69 public void delegates_for_callback() { 70 auto b1=new Button(); 71 auto b2=new Button(); 72 b1.registerHandler( delegate(Button b){b.name="OK";} ); 73 b2.registerHandler( delegate(Button b){b.color="RED";} ); 74 b2.registerHandler( delegate(Button b){b.click_counter--;} ); // can be chained 75 b1.click(); 76 b1.click(); 77 b2.click(); 78 b2.click(); 79 assertEquals(b1.state,FILL_IN_THIS_STRING); 80 assertEquals(b2.state,FILL_IN_THIS_STRING); 81 } 82 83 84 }